package io.bdmc.core.msp2000.utils;

import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import io.bdmc.common.utils.ByteUtil;
import io.bdmc.common.utils.Constant;
import io.bdmc.common.utils.StringUtils;
import io.bdmc.core.msp2000.DataBuild;
import io.bdmc.core.msp2000.DataParse;
import io.bdmc.core.snmp.GwUtil;
import io.bdmc.core.udp.UdpClientSendData;
import io.bdmc.modules.bss.entity.DeviceMachineFms;
import io.bdmc.modules.bss.model.SorEvent;
import io.bdmc.modules.bss.model.SorFileParser;
import io.bdmc.modules.bss.service.IDeviceDeviceService;
import io.bdmc.modules.bss.service.IDeviceMachineFmsService;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
public class FmsDeviceUtil {
    @Autowired
    IDeviceDeviceService deviceService;

    @Autowired
    UdpClientSendData udpClient;

    @Autowired
    IDeviceMachineFmsService fmsService;

    protected static Logger logger = LoggerFactory.getLogger(FmsDeviceUtil.class);

    /**
     * 给fms设备下发参数设置
     * 
     * @param slotPort    卡槽号
     * @param ip          设备ip
     * @param port        设备端口
     * @param endPosition endPosition
     * @param pulseWidth  pulseWidth
     * @param resolution  resolution
     * @param deviceType  deviceType
     * @param fmsDiskSn   fmsDiskSn
     * @return 下发结果
     */
    public Boolean setFmsConfig(Integer slotPort, String ip, int port, String endPosition, String pulseWidth,
            String resolution, String deviceType, String fmsDiskSn) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.writeFMSPara(slotPort + "", endPosition, pulseWidth, resolution, "0", deviceType);
        try {
            String sendData = GwUtil.StrToHex(str) + "0D0A";
            String parseData = getResponseData(ip, port, sendData, deviceType);
            // System.out.println("setFmsConfig:"+ByteUtil.HexToStr(parseData));
            String response = ByteUtil.HexToStr(parseData);
            boolean result = response.contains("ERR0");
            logger.info("下发OTDR配置:" + sendData + "，返回值:" + parseData + ",结果:" + result);
            if (result) {
                UpdateWrapper<DeviceMachineFms> w1 = new UpdateWrapper<>();
                w1.eq("disk_sn", fmsDiskSn).set("end_position", endPosition).set("pulse_width", pulseWidth)
                        .set("resolution", resolution).set("update_time", LocalDateTime.now());
                fmsService.update(w1);
            }
            return result;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 设置fms 折射率
     * 
     * @param slotPort   卡槽号
     * @param ip         ip
     * @param port       端口
     * @param refIndex   折射率
     * @param deviceType 设备类型
     * @return 下发结果
     */
    public boolean setRefIndex(int slotPort, String ip, int port, String refIndex, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.setFMSRefIndex(slotPort, refIndex, deviceType);
        try {
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(str) + "0D0A", deviceType);
            String response = ByteUtil.HexToStr(parseData);
            boolean result = response.contains("ERR0");
            logger.info("下发OTDR折射率:" + parseData + ",结果:" + result);
            return result;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 设置fms测试时间
     * 
     * @param slotPort   卡槽号
     * @param ip         ip
     * @param port       端口
     * @param time       time
     * @param deviceType 设备类型
     * @return 下发结果
     */
    public boolean setFmsTime(int slotPort, String ip, int port, Integer time, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.setFMSTestTime(slotPort, time, deviceType);
        try {
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(str) + "0D0A", deviceType);
            String response = ByteUtil.HexToStr(parseData);
            boolean result = response.contains("ERR0");
            logger.info("下发OTDR设置时间:" + parseData + ",结果:" + result);
            return result;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 读取otdr测试时间
     * 
     * @param slotPort   卡槽号
     * @param ip         ip
     * @param port       端口
     * @param deviceType 设备类型
     * @return 时间
     */
    public String readFMSMeasureTime(int slotPort, String ip, int port, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.readFMSTestTime(slotPort, deviceType);
        try {
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(str) + "0D0A", deviceType);
            String time = DataParse.parseFmsTime(parseData);

            logger.info("读取OTDR测试时间:" + parseData + ",结果:" + time);
            return time;
        } catch (Exception e) {
            log.error(e.getMessage());
            return "";
        }
    }

    /**
     * 读取otdr折射率
     * 
     * @param slotPort   卡槽号
     * @param ip         ip
     * @param port       端口
     * @param deviceType 设备类型
     * @return 时间
     */
    public String readFMSRefIndex(int slotPort, String ip, int port, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.readFMSRefIndex(slotPort, deviceType);
        try {
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(str) + "0D0A", deviceType);
            String refIndex = DataParse.paserfmsRefIndex(parseData);

            logger.info("读取OTDR折射率:" + parseData + ",结果:" + refIndex);
            return refIndex;
        } catch (Exception e) {
            log.error(e.getMessage());
            return "";
        }
    }

    /**
     * 根据ip和端口 卡槽号启动测试
     * 
     * @param slotPort 卡槽号
     * @param ip       ip
     * @param port     端口
     * @return 启动结果
     */
    public boolean startMeasure(int slotPort, String ip, int port, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.FMSStartTest(slotPort + "", deviceType);
        try {
            String sendData = GwUtil.StrToHex(str) + "0D0A";
            String parseData = getResponseData(ip, port, sendData, deviceType);
            String response = ByteUtil.HexToStr(parseData);
            boolean result = response.contains("ERR0");
            logger.info("下发OTDR启动测试:" + sendData + "，返回值：" + response + ",结果:" + result);
            return result;
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 获取FMS状态信息
     * 
     * @param slotPort   卡槽
     * @param ip         ip
     * @param port       端口
     * @param deviceType 设备类型
     * @return 状态
     */
    public String getFmsStatus(int slotPort, String ip, int port, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.FMSReadState(slotPort + "", deviceType);
        try {
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(str) + "0D0A", deviceType);
            String result = DataParse.paserfmsState(parseData);
            logger.info("下发OTDR状态查询结果:" + result);
            return result;
        } catch (Exception e) {
            logger.error("下发OTDR状态异常:" + e.getMessage());
            return "-1";
        }
    }

    /**
     * 获取FMS数据信息
     * 
     * @param slotPort   卡槽
     * @param ip         ip
     * @param port       端口
     * @param deviceType 设备类型
     * @return 状态
     */
    public DeviceMachineFms getFmsData(int slotPort, String ip, int port, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.readFMSPara(slotPort + "", deviceType);
        try {
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(str) + "0D0A", deviceType);
            String response = ByteUtil.HexToStr(parseData);
            logger.info("下发OTDR读取配置数据:" + response);
            return DataParse.parseFmsData(response);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 根据端口获取sor文件
     * 
     * @param slotPort   卡槽号
     * @param ip         ip
     * @param port       端口
     * @param deviceType 设备类型
     * @return sor字节
     */
    public byte[] getFmsSor(int slotPort, String ip, int port, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        try {
            String sorStr = DataBuild.FMSGetSor(slotPort + "", deviceType);
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(sorStr) + "0D0A", deviceType);
            if (!parseData.substring(parseData.length() - 16).contains("436B73756D")) {
                Thread.sleep(1000);
                parseData = getResponseData(ip, port, GwUtil.StrToHex(sorStr) + "0D0A", deviceType);
                logger.info("下发OTDR读取SOR:" + ip + ":" + port + ",sor长度异常headLen:" + parseData.substring(0, 10));
            }
            byte[] sor = ByteUtil.hexToBytes(parseData.substring(10));
            logger.info("下发OTDR读取SOR:" + ip + ":" + port + ",sor长度:" + sor.length + "headLen:"
                    + parseData.substring(0, 10));
            return sor;
        } catch (Exception e) {
            return null;
        }
    }

    public SorFileParser getFmsSorWireless(int slotPort, String ip, int port, String deviceType) {
        SorFileParser parser = null;
        try {
            String msg1 = DataBuild.FMSGetSorWireless(slotPort + "", deviceType);
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(msg1) + "0D0A", deviceType);
            if (parseData.startsWith("3E3C4556454E54")) {
                parser = new SorFileParser();
                String data = parseData.substring(24);
                data = data.substring(0, data.length() - 6);
                String[] para = GwUtil.HexToStr(data).split(",");
                parser.setAcquisitionRangeDistance((int) Double.parseDouble(para[1]));
                parser.setEnd2EndLoss(Double.parseDouble(para[2]));
                parser.setOpticalReturnLoss(para[3]);
                List<SorEvent> sorEvents = new ArrayList<>();
                int eventCount = Integer.parseInt(para[0]);
                for (int i = 0; i < eventCount; i++) {
                    String msg2 = DataBuild.FMSGetSorEventWireless(slotPort + "", (i + 1), deviceType);
                    parseData = getResponseData(ip, port, GwUtil.StrToHex(msg2) + "0D0A", deviceType);
                    if (parseData.startsWith("3E3C4556454E54204C494E4520")) {
                        String line = parseData.substring(26, parseData.length() - 6);
                        String[] para1 = GwUtil.HexToStr(line).split(",");
                        SorEvent event = new SorEvent();
                        event.setEventNumber(Integer.parseInt(para1[0]));
                        // event.setEventPropagationDistance(para1[1]);
                        if (StringUtils.isNotEmpty(para1[1])) {
                            event.setEventPropagationDistance(new BigDecimal(para1[1]).divide(new BigDecimal(1000))
                                    .setScale(3, RoundingMode.HALF_DOWN).toString());
                        }
                        event.setEventLoss(para1[2]);
                        event.setReflcetivity(para1[3]);
                        event.setTotalLosses(para1[4]);
                        event.setEventCode(para1[5]);
                        double attenuationCoefficientLeadInFiber;
                        if (i == 0) {
                            attenuationCoefficientLeadInFiber = (Double.parseDouble(event.getTotalLosses()) - 0 - 0)
                                    / (Double.parseDouble(event.getEventPropagationDistance()) - 0);
                        } else {
                            SorEvent event1 = sorEvents.get(i - 1);
                            attenuationCoefficientLeadInFiber = (Double.parseDouble(event.getTotalLosses())
                                    - Double.parseDouble(event1.getTotalLosses())
                                    - Double.parseDouble(event1.getEventLoss()))
                                    / (Double.parseDouble(event.getEventPropagationDistance())
                                            - Double.parseDouble(event1.getEventPropagationDistance()));
                        }
                        event.setAttenuationCoefficientLeadInFiber(attenuationCoefficientLeadInFiber);
                        sorEvents.add(event);
                    }
                }
                parser.setSorEvents(sorEvents);
            }

        } catch (Exception e) {
            logger.info("下发OTDR读取无线otdr异常:" + e.getMessage());
        }
        return parser;
    }

    /**
     * 通过IP端口和设备类型获取设备响应数据
     * 
     * @param ip         ip
     * @param port       端口
     * @param hexString  发送字符串
     * @param deviceType 设备类型
     * @return 设备返回值
     */
    String getResponseData(String ip, int port, String hexString, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String parseData;
        if (deviceType.equals(Constant.FMSM)) {
            parseData = udpClient.sendTcpData(ip, port, hexString);
        } else {
            parseData = udpClient.sendPollCommand(ip, port, hexString);
        }
        return parseData;
    }

    /***
     * 设置反射阈值
     * 
     * @param slotPort    slotPort
     * @param ip          ip
     * @param port        port
     * @param reflectance reflectance
     * @param deviceType  deviceType
     * @return boolean
     */
    public boolean setFmsReflectanceThreshold(int slotPort, String ip, int port, Integer reflectance,
            String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.setFMSReflectanceThreshold(slotPort, reflectance, deviceType);
        try {
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(str) + "0D0A", deviceType);
            String response = ByteUtil.HexToStr(parseData);
            boolean result = response.contains("ERR0");
            logger.info("下发OTDR设置反射阈值" + parseData + ",结果:" + result);
            return result;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 设置接头损耗阈值
     * 
     * @param slotPort   slotPort
     * @param ip         ip
     * @param port       port
     * @param threshold  threshold
     * @param deviceType deviceType
     * @return boolean
     */
    public boolean setFmsSpliceLossThreshold(int slotPort, String ip, int port, String threshold, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.setFMSSpliceLossThreshold(slotPort, threshold, deviceType);
        try {
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(str) + "0D0A", deviceType);
            String response = ByteUtil.HexToStr(parseData);
            boolean result = response.contains("ERR0");
            logger.info("下发OTDR设置接头损耗阈值" + parseData + ",结果:" + result);
            return result;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 设置光纤终端阈值
     */
    public boolean setFmsEndOfFiberThreshold(int slotPort, String ip, int port, String threshold, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.setFMSEndOfFiberThreshold(slotPort, threshold, deviceType);
        try {
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(str) + "0D0A", deviceType);
            String response = ByteUtil.HexToStr(parseData);
            boolean result = response.contains("ERR0");
            logger.info("下发OTDR设置光纤终端阈值" + parseData + ",结果:" + result);
            return result;
        } catch (Exception e) {
            log.error(e.getMessage());
            return false;
        }
    }

    /**
     * 读取OTDR反射阈值
     */
    public String readFmsReflectanceThreshold(int slotPort, String ip, int port, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.readFMSReflectanceThreshold(slotPort, deviceType);
        try {
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(str) + "0D0A", deviceType);
            String refIndex = DataParse.paserfmsReflectanceThreshold(parseData);

            logger.info("读取OTDR反射阈值:" + parseData + ",结果:" + refIndex);
            return refIndex;
        } catch (Exception e) {
            log.error(e.getMessage());
            return "";
        }
    }

    /***
     * 读取OTDR接头损耗阈值
     */
    public String readFmsSpliceLossThreshold(int slotPort, String ip, int port, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.readFMSSpliceLossThreshold(slotPort, deviceType);
        try {
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(str) + "0D0A", deviceType);
            String refIndex = DataParse.paserfmsReflectanceThreshold(parseData);

            logger.info("读取OTDR接头损耗阈值:" + parseData + ",结果:" + refIndex);
            return refIndex;
        } catch (Exception e) {
            log.error(e.getMessage());
            return "";
        }
    }

    /**
     * 读取OTDR光纤终端阈值
     */
    public String readFmsEndOfFiberThreshold(int slotPort, String ip, int port, String deviceType) {
        if (deviceType.equals(Constant.FMSA))
            deviceType = Constant.FMSM;
        String str = DataBuild.readFMSEndOfFiberThreshold(slotPort, deviceType);
        try {
            String parseData = getResponseData(ip, port, GwUtil.StrToHex(str) + "0D0A", deviceType);
            String refIndex = DataParse.paserfmsReflectanceThreshold(parseData);

            logger.info("读取OTDR光纤终端阈值:" + parseData + ",结果:" + refIndex);
            return refIndex;
        } catch (Exception e) {
            log.error(e.getMessage());
            return "";
        }
    }

}
